﻿
//是否使用brdf 贴图
//#define _MODEL_BRDF_QUALITY_HIGH_

//#define _RES_WIN32_
//#define _RES_ANDROID_
//#define _RES_IOS_

using UnityEngine;
using System.IO;
using UnityEditor;
using System.Collections.Generic;
using Object = UnityEngine.Object;
//using Dictionary = System.Collections.Generic.Dictionary<string,string>;


public class CommonABConfig
{
    public static string WindowsBuildPath = "builds";
    public static string AndroidBuildPath = "builds_android";
    public static string IOSBuildPath = "builds_ios";
    
    //资源地址
    public static string APPLICATION_PATH = Application.dataPath + "/";

    //工程地址
    public static string PROJECT_PATH = APPLICATION_PATH.Substring(0, APPLICATION_PATH.Length - 7);
    
    //AssetBundle打包的后缀名
    public static string SUFFIX = ".unity3d";
    
}

public class SpineABConfig
{
    public static string TargetPath = "{0}/../../GameClient_GamePlay/{1}/AssetBundles/model/spine_anim";

    //此处添加需要命名assetBundleName的资源后缀名,注意大小写。
    public static Dictionary<string, string> suffixDirMap = new Dictionary<string, string>() {
        { ".prefab","prefab"},
        {  ".mat","material"},
        {  ".png","texpng"},
        {  ".json","json"},
        {  ".txt","txt"},
        {  ".asset","asset"},
        { ".bytes","skelbytes"},
    };
}

public class VfxABConfig
{
    public static string TargetPath = "{0}/../../GameClient_GamePlay/{1}/AssetBundles/effects/slg_effect";

    //此处添加需要命名assetBundleName的资源后缀名,注意大小写。
    public static Dictionary<string, string> suffixDirMap = new Dictionary<string, string>() {
        { ".prefab","prefab"},
        {  ".mat","material"},
        {  ".tga","textga"},
        {  ".json","json"},
        {  ".txt","txt"},
        {  ".asset","asset"},
        { ".anim","animation"},
        { ".controller","controller"},
        { ".fbx","modelfbx"},
        {  ".png","texpng"},
        { ".bytes","skelbytes"},
    };
}

public class ModelABConfig
{
    public static string TargetPath = "{0}/../../GameClient_GamePlay/{1}/AssetBundles/model/slg_model";

    //此处添加需要命名assetBundleName的资源后缀名,注意大小写。
    public static Dictionary<string, string> suffixDirMap = new Dictionary<string, string>() {
        { ".prefab","prefab"},
        {  ".mat","material"},
        {  ".tga","textga"},
        {  ".json","json"},
        {  ".txt","txt"},
        {  ".asset","asset"},
        { ".anim","animation"},
        { ".controller","controller"},
        { ".fbx","modelfbx"},
    };
}

public class HUBuildDataBundle
{
    static private string m_ExportPath = string.Empty;

    static private string[] fullPaths = new string[0];

    static Dictionary<string, string> SuffixDirPathMap = new Dictionary<string, string>();

    //#if _MODEL_BRDF_QUALITY_HIGH_
    //	static string model_res_path = "model_res_high_quality";
    //    public static bool is_use_brdf_quality = true;
    //	public static string use_brdf_quality = "use BRDF HIGH Quality";
    //	static string quelity_end = "_high_quality";
    //#else
    //    static string model_res_path = "model_res";
    //    public static bool is_use_brdf_quality = false;
    //    public static string use_brdf_quality = "use SOSO Quality";
    //    static string quelity_end = "";
    //#endif

    //#if _RES_WIN32_
    //    public static string BuildsPath = "builds";
    //    public static string TargetType = "win32";
    //    public static BuildTarget BuildTargetOpt = BuildTarget.StandaloneWindows64;
    //#elif _RES_ANDROID_
    //	public static string BuildsPath = "builds_android";
    //	public static string TargetType = "android";
    //    public static BuildTarget BuildTargetOpt = BuildTarget.Android;
    //#elif _RES_IOS_
    //    public static string BuildsPath = "builds_ios";
    //    public static string TargetType = "ios";
    //    public static BuildTarget BuildTargetOpt = BuildTarget.iOS;
    //#endif

    #region Spine动画资源
    [MenuItem("New AB Editor/Build Spine/Build For Windows")]
    public static void BuildSpineForWindows()
    {
        MakeSpineResouceAb("builds");
    }

    [MenuItem("New AB Editor/Build Spine/Build For Android")]
    public static void BuildSpineForAndroid()
    {
        MakeSpineResouceAb("builds_android");
    }

    [MenuItem("New AB Editor/Build Spine/Build For IOS")]
    public static void BuildSpineForIOS()
    {
        MakeSpineResouceAb("builds_ios");
    }

    public static void MakeSpineResouceAb(string buildsPath)
    {
        string targetPath;
        BuildTarget targetBuild;
        if (buildsPath == "builds")
        {
            targetPath = string.Format(SpineABConfig.TargetPath, Application.dataPath, CommonABConfig.WindowsBuildPath);
            targetBuild = BuildTarget.StandaloneWindows64;
        }
        else if (buildsPath == "builds_android")
        {
            targetPath = string.Format(SpineABConfig.TargetPath, Application.dataPath, CommonABConfig.AndroidBuildPath);
            targetBuild = BuildTarget.Android;

        }
        else if (buildsPath == "builds_ios")
        {
            targetPath = string.Format(SpineABConfig.TargetPath, Application.dataPath, CommonABConfig.IOSBuildPath);
            targetBuild = BuildTarget.iOS;

        }
        else
        {
            Debug.LogErrorFormat("no this config in HuBuildNewBundle,please check it");
            return;
        }

        //此处扩展目录
        //fullPaths = new string[]
        //{
        //    Application.dataPath + "/Resources/SpineAnim/",
        //    //Application.dataPath + "/Texture"
        //};

        List<string> ret = new List<string>();
        ret.AddRange(GetAllModelPrefabPath("Assets/Resources/SpineAnim"));

        fullPaths = ret.ToArray();

        OneKeyToMakeBundleImpl(targetPath, targetBuild, SpineABConfig.suffixDirMap);
    }
    #endregion

    #region Vfx特效资源
    [MenuItem("New AB Editor/Build Vfx/Build For Windows")]
    public static void BuildVfxForWindows()
    {
        MakeVfxResouceAb("builds");
    }

    [MenuItem("New AB Editor/Build Vfx/Build For Android")]
    public static void BuildVfxForAndroid()
    {
        MakeVfxResouceAb("builds_android");
    }

    [MenuItem("New AB Editor/Build Vfx/Build For IOS")]
    public static void BuildVfxForIOS()
    {
        MakeVfxResouceAb("builds_ios");
    }

    public static void MakeVfxResouceAb(string buildsPath)
    {
        string targetPath;
        BuildTarget targetBuild;
        if (buildsPath == "builds")
        {
            targetPath = string.Format(VfxABConfig.TargetPath, Application.dataPath, CommonABConfig.WindowsBuildPath);
            targetBuild = BuildTarget.StandaloneWindows64;
        }
        else if (buildsPath == "builds_android")
        {
            targetPath = string.Format(VfxABConfig.TargetPath, Application.dataPath, CommonABConfig.AndroidBuildPath);
            targetBuild = BuildTarget.Android;

        }
        else if (buildsPath == "builds_ios")
        {
            targetPath = string.Format(VfxABConfig.TargetPath, Application.dataPath, CommonABConfig.IOSBuildPath);
            targetBuild = BuildTarget.iOS;

        }
        else
        {
            Debug.LogErrorFormat("no this config in HuBuildNewBundle,please check it");
            return;
        }

        //此处扩展目录
        //fullPaths = new string[]
        //{
        //    Application.dataPath + "/Resources/vfx/slg",
        //};

        //此处扩展目录
        List<string> ret = new List<string>();
        ret.AddRange(GetAllModelPrefabPath("Assets/Resources/vfx/slg"));

        fullPaths = ret.ToArray();

        OneKeyToMakeBundleImpl(targetPath, targetBuild, VfxABConfig.suffixDirMap);
    }
    #endregion

    #region model模型资源
    [MenuItem("New AB Editor/Build Model/Build For Windows")]
    public static void BuildModelForWindows()
    {
        MakeModelResouceAb("builds");
    }

    [MenuItem("New AB Editor/Build Model/Build For Android")]
    public static void BuildModelForAndroid()
    {
        MakeModelResouceAb("builds_android");
    }

    [MenuItem("New AB Editor/Build Model/Build For IOS")]
    public static void BuildModelForIOS()
    {
        MakeModelResouceAb("builds_ios");
    }

    public static void MakeModelResouceAb(string buildsPath)
    {
        string targetPath;
        BuildTarget targetBuild;
        if (buildsPath == "builds")
        {
            targetPath = string.Format(ModelABConfig.TargetPath, Application.dataPath, CommonABConfig.WindowsBuildPath);
            targetBuild = BuildTarget.StandaloneWindows64;
        }
        else if (buildsPath == "builds_android")
        {
            targetPath = string.Format(ModelABConfig.TargetPath, Application.dataPath, CommonABConfig.AndroidBuildPath);
            targetBuild = BuildTarget.Android;

        }
        else if (buildsPath == "builds_ios")
        {
            targetPath = string.Format(ModelABConfig.TargetPath, Application.dataPath, CommonABConfig.IOSBuildPath);
            targetBuild = BuildTarget.iOS;

        }
        else
        {
            Debug.LogErrorFormat("no this config in HuBuildNewBundle,please check it");
            return;
        }

        //此处扩展目录
        List<string> ret = new List<string>();
        ret.AddRange(GetAllModelPrefabPath("Assets/Resources/slg_model"));

        fullPaths = ret.ToArray();       

        OneKeyToMakeBundleImpl(targetPath, targetBuild, ModelABConfig.suffixDirMap);
    }

    private static string[] GetAllModelPrefabPath(string dirPath)
    {
        List<string> ret = new List<string>();
        if (Directory.Exists(dirPath))
        {
            DirectoryInfo dir = new DirectoryInfo(dirPath);

            var files = dir.GetFiles("*.prefab", SearchOption.AllDirectories);
            
            for (var i = 0; i < files.Length; ++i)
            {
                var fileInfo = files[i];
                if (fileInfo.Name.EndsWith(".prefab") )
                {
                    string str = fileInfo.FullName.Replace("\\", "/");
                    str = str.Replace(CommonABConfig.PROJECT_PATH, "");
                    ret.Add(str);
                }
               
            }

        }

        return ret.ToArray();
    }
    #endregion

    #region  通用
    public static void OneKeyToMakeBundleImpl(string path,BuildTarget buildTarget,Dictionary<string,string> suffixDirMap)
    {
        SetExportPath(path);
        SetFilterInfo(suffixDirMap);

        if(fullPaths.Length == 0)
        {
            if (CheckSelectValid(ref fullPaths) == false)
            {
                return;
            }
        }

        string messageStr = GetMessageStr(fullPaths);

        if (EditorUtility.DisplayDialog("制作AssetBundle确认", string.Format("你要制作AB包的来源为{0},输出目录为{1}", messageStr, m_ExportPath), "confirm", "cancel"))
        {
            string[] names = AssetDatabase.GetAllAssetBundleNames();
            if (names.Length != 0)
            {
                SetOrClearResourcesABName(CommonABConfig.APPLICATION_PATH, true);//有名字没清空，先把所有文件的AssetbundleName清空
            }
            List<string> dependencies = GetDependenciesPath(fullPaths);
            for (int i = 0; i < dependencies.Count; i++)
            {
                SetOrClearResourcesABName(dependencies[i], false);//设置指定路径的文件或目录的ABname

                EditorUtility.DisplayProgressBar("设置AssetName名称", "正在设置AssetName名称中...",
                    1f * i / dependencies.Count);                
                
            }
            EditorUtility.ClearProgressBar();

            AssetBundleManifest abm = BuildPipeline.BuildAssetBundles(
             m_ExportPath,
				BuildAssetBundleOptions.ChunkBasedCompression |
             BuildAssetBundleOptions.DeterministicAssetBundle,
             buildTarget);
            for (int i = 0; i < dependencies.Count; i++)
            {
                SetOrClearResourcesABName(dependencies[i], true);//打完ab包，清除指定路径的文件或目录的ABname

                EditorUtility.DisplayProgressBar("清除AssetName名称", "正在清除AssetName名称中...",
                                        1f * i / dependencies.Count);
            }
            EditorUtility.ClearProgressBar();
        }

        EditorUtility.DisplayDialog("制作AB包完成", string.Format("输出目录为{0}", m_ExportPath), "收到");
    }
    
    //[MenuItem("New AB Editor/GetAllAssetBundleName")]
    static void GetAllAssetBundleName()
    {

        string[] names = AssetDatabase.GetAllAssetBundleNames();

        foreach (var name in names)
        {
            Debug.Log(name);
        }

    }

    //[MenuItem("New AB Editor/ClearAssetBundleName")]
    static void ClearResourcesAssetBundleName()
    {
        string[] fullPaths = GetSelectPaths();

        if (fullPaths.Length == 0)
        {
            if (EditorUtility.DisplayDialog("提示", "请至少选择一个目录或者文件", "ok"))
            {
                return;
            }
            return;
        }

        string messageStr = string.Empty;
        for (int i = 0; i < fullPaths.Length; i++)
        {
            messageStr += fullPaths[i] + "\r\n";
        }

        if (EditorUtility.DisplayDialog("清除AssetName名称确认", string.Format("你要清除AssetName的位置为{0}", messageStr), "confirm", "cancel"))
        {
            for (int i = 0; i < fullPaths.Length; i++)
            {
                SetOrClearResourcesABName(fullPaths[i], true);
            }
            EditorUtility.ClearProgressBar();
            AssetDatabase.RemoveUnusedAssetBundleNames();
        }

    }

    private static string GetMessageStr(string[] fullPaths)
    {
        string messageStr = "\r\n";
        for (int i = 0; i < fullPaths.Length; i++)
        {
            //messageStr += fullPaths[i].Substring(Application.dataPath.Length) + "\r\n";
            messageStr += fullPaths[i] + "\r\n";
        }

        return messageStr;
    }

    private static bool CheckSelectValid(ref string[]  fullPaths)
    {
         fullPaths = GetSelectPaths();

        if (fullPaths.Length == 0)
        {
            if (EditorUtility.DisplayDialog("提示", "请至少选择一个目录或者文件", "ok"))
            {
                return false;
            }
            return false;
        }
        else
        {
            return true;
        }

    }

    private static void SetFilterInfo(Dictionary<string,string> suffixDirMap)
    {
        SuffixDirPathMap = suffixDirMap;
    }

    private static void SetExportPath(string path)
    {
        m_ExportPath = path;

        if (Directory.Exists(m_ExportPath) == false)
        {
            Directory.CreateDirectory(m_ExportPath);
        }

    }

    private static void SetOrClearFileABName(FileInfo fileInfo, bool clear = false)
    {
        foreach (var item in SuffixDirPathMap)
        {
            string suffix = item.Key;
            string dirName = item.Value;

            if (fileInfo.Name.EndsWith(suffix, true, null))
            {
                string path = fileInfo.FullName.Replace('\\', '/').Substring(CommonABConfig.PROJECT_PATH.Length);
                var importer = AssetImporter.GetAtPath(path);
                if (importer)
                {
                    if (clear)
                    {
                        importer.assetBundleName = null;
                    }
                    else
                    {
                        string name = fileInfo.Name;
                        importer.assetBundleName = dirName + "/" + name.Substring(0, name.LastIndexOf('.')) + CommonABConfig.SUFFIX;
                    }
                }
            }
        }
    }

    static void SetOrClearResourcesABName(string fullPath, bool clear)
    {
        if (Directory.Exists(fullPath))
        {
            DirectoryInfo dir = new DirectoryInfo(fullPath);

            var files = dir.GetFiles("*", SearchOption.AllDirectories);
            ;
            for (var i = 0; i < files.Length; ++i)
            {
                var fileInfo = files[i];
                if (fileInfo.Name.EndsWith(".meta") && clear == false)//添加标记的时候meta过滤掉
                {
                    continue;
                }
               

                SetOrClearFileABName(fileInfo, clear);
            }

        }
        else if (File.Exists(fullPath))
        {
            FileInfo fileInfo = new FileInfo(fullPath);

            SetOrClearFileABName(fileInfo, clear);
        }

        if (clear == true)
        {
            AssetDatabase.RemoveUnusedAssetBundleNames();
        }

       
    }

    static string[] GetSelectPaths()
    {
        UnityEngine.Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.Unfiltered);
        //此处添加需要命名的资源后缀名,注意大小写。
        string[] paths = new string[SelectedAsset.Length];

        for (int i = 0; i < paths.Length; i++)
        {
            paths[i] = CommonABConfig.PROJECT_PATH + AssetDatabase.GetAssetPath(SelectedAsset[i]);
        }

        return paths;
    }

    /// <summary>
    /// 得到指定prefab的依赖列表
    /// </summary>
    /// <param name="prefabPaths"></param>
    /// <returns></returns>
    public static List<string> GetDependenciesPath(string[] prefabPaths)
    {
        List<string> ret = new List<string>();
        for (int i = 0; i < prefabPaths.Length; i++)
        {
            List<string> temps = GetDependenciesPath(prefabPaths[i]);
            for (int j = 0; j < temps.Count; j++)
            {
                if (ret.Contains(temps[j]) == false)
                {
                    ret.Add(temps[j]);
                }
            }
            EditorUtility.DisplayProgressBar("收集依赖信息", "信息收集中。。。", 1f * i / prefabPaths.Length);
        }
        EditorUtility.ClearProgressBar();

        return ret;
    }

    /// <summary>
    /// 得到指定prefab的依赖列表
    /// </summary>
    /// <param name="prefabPath"></param>
    /// <returns></returns>
    public static List<string> GetDependenciesPath(string prefabPath)
    {
        //参数是数组，可以同时查找多个prefab
        //"Assets/scene_tools/create_scene/create_world_scene/create_world_scene.prefab"
        string[] paths = AssetDatabase.GetDependencies(prefabPath);
        List<string> ret = new List<string>();
        foreach (string path in paths)
        {
            //Debug.Log(path);
            if (ret.Contains(path) == false)
            {
                ret.Add(path);

            }
        }

        return ret;
    }
    #endregion
}

